<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>React16_4整理-上阶 | aiyoudiao</title>
    <meta name="generator" content="VuePress 1.9.10" />
    <link rel="icon" href="/img/blog.ico">
    <script src="https://cdn.jsdelivr.net/npm/live2d-widget@3.1.4/lib/L2Dwidget.min.js"></script> <meta name="description" content="码二~">
    <meta name="keywords" content="前端博客,个人技术博客,前端,前端开发,前端框架,web前端,前端面试题,技术文档,学习,面试,JavaScript,js,ES6,TypeScript,vue,python,css3,html5,Node,git,github,gitee,markdown">
    <meta name="theme-color" content="#11a8cd">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <link rel="preload" href="/assets/css/0.styles.146197cf.css" as="style"><link rel="preload" href="/assets/js/app.bd2fbc77.js" as="script"><link rel="preload" href="/assets/js/3.72c9c947.js" as="script"><link rel="preload" href="/assets/js/112.352fa217.js" as="script"><link rel="preload" href="/assets/js/42.4251ca36.js" as="script"><link rel="prefetch" href="/assets/js/1.4ed4671d.js"><link rel="prefetch" href="/assets/js/10.bd6ddb58.js"><link rel="prefetch" href="/assets/js/100.20d2348f.js"><link rel="prefetch" href="/assets/js/101.ba7b784c.js"><link rel="prefetch" href="/assets/js/102.c3e2dcae.js"><link rel="prefetch" href="/assets/js/103.0f4c50f3.js"><link rel="prefetch" href="/assets/js/104.ef47a111.js"><link rel="prefetch" href="/assets/js/105.2e00f516.js"><link rel="prefetch" href="/assets/js/106.b50e19b9.js"><link rel="prefetch" href="/assets/js/107.e125a8f6.js"><link rel="prefetch" href="/assets/js/108.770493ab.js"><link rel="prefetch" href="/assets/js/109.74766d7b.js"><link rel="prefetch" href="/assets/js/11.f786a5ee.js"><link rel="prefetch" href="/assets/js/110.0b0ee5b4.js"><link rel="prefetch" href="/assets/js/111.835b0e44.js"><link rel="prefetch" href="/assets/js/113.4e908557.js"><link rel="prefetch" href="/assets/js/114.7b77996d.js"><link rel="prefetch" href="/assets/js/115.bdc61268.js"><link rel="prefetch" href="/assets/js/116.d5da9b8b.js"><link rel="prefetch" href="/assets/js/117.35ab1f9f.js"><link rel="prefetch" href="/assets/js/118.517c151d.js"><link rel="prefetch" href="/assets/js/119.f7f49ba8.js"><link rel="prefetch" href="/assets/js/12.3c729a65.js"><link rel="prefetch" href="/assets/js/120.b559598b.js"><link rel="prefetch" href="/assets/js/121.bf8a2f43.js"><link rel="prefetch" href="/assets/js/122.11a0bc97.js"><link rel="prefetch" href="/assets/js/123.2bafdde7.js"><link rel="prefetch" href="/assets/js/124.dc393688.js"><link rel="prefetch" href="/assets/js/125.ed3f389a.js"><link rel="prefetch" href="/assets/js/126.8fd9a57d.js"><link rel="prefetch" href="/assets/js/127.3bf2a1f2.js"><link rel="prefetch" href="/assets/js/128.b9c671d3.js"><link rel="prefetch" href="/assets/js/129.5d331f0d.js"><link rel="prefetch" href="/assets/js/13.7b1a1fe5.js"><link rel="prefetch" href="/assets/js/130.53e4f9c6.js"><link rel="prefetch" href="/assets/js/131.dcc47e1d.js"><link rel="prefetch" href="/assets/js/132.692dcdcd.js"><link rel="prefetch" href="/assets/js/133.e293202c.js"><link rel="prefetch" href="/assets/js/134.593dccf2.js"><link rel="prefetch" href="/assets/js/135.d76d384b.js"><link rel="prefetch" href="/assets/js/136.a519c23c.js"><link rel="prefetch" href="/assets/js/137.b1821288.js"><link rel="prefetch" href="/assets/js/138.5bcea4ef.js"><link rel="prefetch" href="/assets/js/139.076664b0.js"><link rel="prefetch" href="/assets/js/14.35f257b2.js"><link rel="prefetch" href="/assets/js/140.a019e655.js"><link rel="prefetch" href="/assets/js/141.1f70e1c7.js"><link rel="prefetch" href="/assets/js/142.5ed728fd.js"><link rel="prefetch" href="/assets/js/143.1c8cdc78.js"><link rel="prefetch" href="/assets/js/144.b0cb125b.js"><link rel="prefetch" href="/assets/js/145.c0209a76.js"><link rel="prefetch" href="/assets/js/146.551469f4.js"><link rel="prefetch" href="/assets/js/147.1dfd721d.js"><link rel="prefetch" href="/assets/js/148.91d07ef5.js"><link rel="prefetch" href="/assets/js/149.5b88b710.js"><link rel="prefetch" href="/assets/js/15.23bbc29a.js"><link rel="prefetch" href="/assets/js/150.8301107f.js"><link rel="prefetch" href="/assets/js/151.867da089.js"><link rel="prefetch" href="/assets/js/152.935d5046.js"><link rel="prefetch" href="/assets/js/153.f39d8435.js"><link rel="prefetch" href="/assets/js/154.6b9eb2c3.js"><link rel="prefetch" href="/assets/js/155.14283ad4.js"><link rel="prefetch" href="/assets/js/156.2d7c1a2a.js"><link rel="prefetch" href="/assets/js/157.2f28d02f.js"><link rel="prefetch" href="/assets/js/158.151221ae.js"><link rel="prefetch" href="/assets/js/159.ef6d7ffe.js"><link rel="prefetch" href="/assets/js/16.1793aef7.js"><link rel="prefetch" href="/assets/js/160.de54c4ea.js"><link rel="prefetch" href="/assets/js/161.24d4e57c.js"><link rel="prefetch" href="/assets/js/162.632032fe.js"><link rel="prefetch" href="/assets/js/163.fd01cd99.js"><link rel="prefetch" href="/assets/js/164.45f203f5.js"><link rel="prefetch" href="/assets/js/165.aafe4fe1.js"><link rel="prefetch" href="/assets/js/166.1dd1d21c.js"><link rel="prefetch" href="/assets/js/167.5501b3a1.js"><link rel="prefetch" href="/assets/js/168.fbe58b1f.js"><link rel="prefetch" href="/assets/js/169.2cae7f5e.js"><link rel="prefetch" href="/assets/js/17.bbfe63f2.js"><link rel="prefetch" href="/assets/js/170.265f7c9e.js"><link rel="prefetch" href="/assets/js/171.b61f327d.js"><link rel="prefetch" href="/assets/js/172.5d0043fd.js"><link rel="prefetch" href="/assets/js/173.45284bb6.js"><link rel="prefetch" href="/assets/js/174.9130e0c4.js"><link rel="prefetch" href="/assets/js/175.2b38bddd.js"><link rel="prefetch" href="/assets/js/176.9772cf09.js"><link rel="prefetch" href="/assets/js/177.69048ebc.js"><link rel="prefetch" href="/assets/js/178.e10d7ce5.js"><link rel="prefetch" href="/assets/js/179.3789edc0.js"><link rel="prefetch" href="/assets/js/18.0807ded0.js"><link rel="prefetch" href="/assets/js/180.ab675e47.js"><link rel="prefetch" href="/assets/js/181.2e39eff0.js"><link rel="prefetch" href="/assets/js/19.becf5a76.js"><link rel="prefetch" href="/assets/js/2.eb089a4f.js"><link rel="prefetch" href="/assets/js/20.cea59652.js"><link rel="prefetch" href="/assets/js/21.58c43ff1.js"><link rel="prefetch" href="/assets/js/22.f73b825d.js"><link rel="prefetch" href="/assets/js/23.43b13730.js"><link rel="prefetch" href="/assets/js/24.f77f93ca.js"><link rel="prefetch" href="/assets/js/25.7dfaf3fb.js"><link rel="prefetch" href="/assets/js/26.629d28e5.js"><link rel="prefetch" href="/assets/js/27.4fff23ea.js"><link rel="prefetch" href="/assets/js/28.1b8ae389.js"><link rel="prefetch" href="/assets/js/29.d5cce9a0.js"><link rel="prefetch" href="/assets/js/30.961d5519.js"><link rel="prefetch" href="/assets/js/31.121dd1af.js"><link rel="prefetch" href="/assets/js/32.4a3c5df7.js"><link rel="prefetch" href="/assets/js/33.5537f44b.js"><link rel="prefetch" href="/assets/js/34.1d4d4653.js"><link rel="prefetch" href="/assets/js/35.d094209b.js"><link rel="prefetch" href="/assets/js/36.832660c5.js"><link rel="prefetch" href="/assets/js/37.145c3665.js"><link rel="prefetch" href="/assets/js/38.4f369bfe.js"><link rel="prefetch" href="/assets/js/39.ba060044.js"><link rel="prefetch" href="/assets/js/4.66d742f6.js"><link rel="prefetch" href="/assets/js/40.e50e0379.js"><link rel="prefetch" href="/assets/js/41.4ed7617c.js"><link rel="prefetch" href="/assets/js/43.d22b74c4.js"><link rel="prefetch" href="/assets/js/44.59439f9d.js"><link rel="prefetch" href="/assets/js/45.da28bc46.js"><link rel="prefetch" href="/assets/js/46.b8db1176.js"><link rel="prefetch" href="/assets/js/47.7ed16fc7.js"><link rel="prefetch" href="/assets/js/48.c982d5ed.js"><link rel="prefetch" href="/assets/js/49.a7579f55.js"><link rel="prefetch" href="/assets/js/5.08802d7d.js"><link rel="prefetch" href="/assets/js/50.103b5bf6.js"><link rel="prefetch" href="/assets/js/51.0fe9d79a.js"><link rel="prefetch" href="/assets/js/52.9ba31e26.js"><link rel="prefetch" href="/assets/js/53.0e8bc1f0.js"><link rel="prefetch" href="/assets/js/54.9566e517.js"><link rel="prefetch" href="/assets/js/55.a124abae.js"><link rel="prefetch" href="/assets/js/56.d9cf0800.js"><link rel="prefetch" href="/assets/js/57.93599da0.js"><link rel="prefetch" href="/assets/js/58.d943f85b.js"><link rel="prefetch" href="/assets/js/59.50a66488.js"><link rel="prefetch" href="/assets/js/6.a3ea60eb.js"><link rel="prefetch" href="/assets/js/60.21aa3aa3.js"><link rel="prefetch" href="/assets/js/61.6712c00f.js"><link rel="prefetch" href="/assets/js/62.eff3e4b1.js"><link rel="prefetch" href="/assets/js/63.09701d5a.js"><link rel="prefetch" href="/assets/js/64.eb440dec.js"><link rel="prefetch" href="/assets/js/65.aeed0579.js"><link rel="prefetch" href="/assets/js/66.97244c64.js"><link rel="prefetch" href="/assets/js/67.e01c5c24.js"><link rel="prefetch" href="/assets/js/68.21be91ba.js"><link rel="prefetch" href="/assets/js/69.c0849905.js"><link rel="prefetch" href="/assets/js/7.7fd40e91.js"><link rel="prefetch" href="/assets/js/70.b32bbe5d.js"><link rel="prefetch" href="/assets/js/71.0efbc0c7.js"><link rel="prefetch" href="/assets/js/72.ef963181.js"><link rel="prefetch" href="/assets/js/73.ca7dd5db.js"><link rel="prefetch" href="/assets/js/74.4483ede8.js"><link rel="prefetch" href="/assets/js/75.374ab483.js"><link rel="prefetch" href="/assets/js/76.b4a39f08.js"><link rel="prefetch" href="/assets/js/77.6b30c3cd.js"><link rel="prefetch" href="/assets/js/78.15376c33.js"><link rel="prefetch" href="/assets/js/79.3153fcec.js"><link rel="prefetch" href="/assets/js/80.9a88c684.js"><link rel="prefetch" href="/assets/js/81.1e3f842c.js"><link rel="prefetch" href="/assets/js/82.996dbd3d.js"><link rel="prefetch" href="/assets/js/83.955158bf.js"><link rel="prefetch" href="/assets/js/84.71bdc76d.js"><link rel="prefetch" href="/assets/js/85.774e49f2.js"><link rel="prefetch" href="/assets/js/86.bebf32e5.js"><link rel="prefetch" href="/assets/js/87.becdbde1.js"><link rel="prefetch" href="/assets/js/88.49e933f4.js"><link rel="prefetch" href="/assets/js/89.eeceedfd.js"><link rel="prefetch" href="/assets/js/90.3ea6dd12.js"><link rel="prefetch" href="/assets/js/91.62a6a556.js"><link rel="prefetch" href="/assets/js/92.e2ebb8f5.js"><link rel="prefetch" href="/assets/js/93.dcdefe7a.js"><link rel="prefetch" href="/assets/js/94.bf412146.js"><link rel="prefetch" href="/assets/js/95.8deadcdc.js"><link rel="prefetch" href="/assets/js/96.9977087a.js"><link rel="prefetch" href="/assets/js/97.6591f9da.js"><link rel="prefetch" href="/assets/js/98.4db7f75e.js"><link rel="prefetch" href="/assets/js/99.a61462e9.js"><link rel="prefetch" href="/assets/js/vendors~docsearch.2852b102.js"> <link rel="stylesheet" href="/assets/css/0.styles.146197cf.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" width="50" height="50" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="https://p3-passport.byteacctimg.com/img/user-avatar/794fdae4ff249d532da19a3c26d420ed~300x300.image" alt="aiyoudiao" class="logo"> <span class="site-name can-hide">
      aiyoudiao
    </span></a> <div class="links"><div class="sky-switch" data-v-3a03d589><label for="toggle" data-v-3a03d589><input id="toggle" type="checkbox" data-v-3a03d589><div data-v-3a03d589></div></label></div> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="笔记" class="dropdown-title"><!----> <span class="title" style="display:;">笔记</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/84633490449/" class="nav-link">
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/pages/2331001041/" class="nav-link">
  Vue
</a></li><li class="dropdown-item"><!----> <a href="/pages/18114480448/" class="nav-link">
  React
</a></li><li class="dropdown-item"><!----> <a href="/pages/25236260426/" class="nav-link">
  低代码
</a></li><li class="dropdown-item"><!----> <a href="/pages/35345230523/" class="nav-link">
  线性系统
</a></li><li class="dropdown-item"><!----> <a href="/pages/08313561056/" class="nav-link">
  暂未分类
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="算法与设计" class="dropdown-title"><!----> <span class="title" style="display:;">算法与设计</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/70741550255/" class="nav-link">
  LeetCode
</a></li><li class="dropdown-item"><!----> <a href="/pages/17845450445/" class="nav-link">
  算法
</a></li><li class="dropdown-item"><!----> <a href="/pages/90132170217/" class="nav-link">
  数据结构
</a></li><li class="dropdown-item"><!----> <a href="/pages/50546120212/" class="nav-link">
  设计模式
</a></li><li class="dropdown-item"><!----> <a href="/pages/02344550255/" class="nav-link">
  Other
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="技能" class="dropdown-title"><!----> <span class="title" style="display:;">技能</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/82158160216/" class="nav-link">
  PMP
</a></li><li class="dropdown-item"><!----> <a href="/pages/41858590259/" class="nav-link">
  Office
</a></li><li class="dropdown-item"><!----> <a href="/pages/02359360236/" class="nav-link">
  面试
</a></li><li class="dropdown-item"><!----> <a href="/pages/73600130213/" class="nav-link">
  Bash
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="历程" class="dropdown-title"><!----> <span class="title" style="display:;">历程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/83857320232/" class="nav-link">
  流年往事
</a></li><li class="dropdown-item"><!----> <a href="/pages/93419130213/" class="nav-link">
  经验片段
</a></li><li class="dropdown-item"><!----> <a href="/pages/99744220322/" class="nav-link">
  读书杂感
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="首页" class="dropdown-title"><!----> <span class="title" style="display:;">首页</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">
  归档
</a></li><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">
  分类
</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">
  标签
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="其它" class="dropdown-title"><!----> <span class="title" style="display:;">其它</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/02657130213/" class="nav-link">
  简介
</a></li><li class="dropdown-item"><!----> <a href="/pages/5390102042/" class="nav-link">
  收藏
</a></li><li class="dropdown-item"><!----> <a href="/pages/32309510451/" class="nav-link">
  有趣
</a></li><li class="dropdown-item"><!----> <a href="/pages/23313210521/" class="nav-link">
  文档
</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><div class="blogger"><img src="/img/mar.jpg"> <div class="blogger-info"><h3>码二</h3> <span>扫微信二维码，认识一下码二吧😉。</span></div></div> <nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="笔记" class="dropdown-title"><!----> <span class="title" style="display:;">笔记</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/84633490449/" class="nav-link">
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/pages/2331001041/" class="nav-link">
  Vue
</a></li><li class="dropdown-item"><!----> <a href="/pages/18114480448/" class="nav-link">
  React
</a></li><li class="dropdown-item"><!----> <a href="/pages/25236260426/" class="nav-link">
  低代码
</a></li><li class="dropdown-item"><!----> <a href="/pages/35345230523/" class="nav-link">
  线性系统
</a></li><li class="dropdown-item"><!----> <a href="/pages/08313561056/" class="nav-link">
  暂未分类
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="算法与设计" class="dropdown-title"><!----> <span class="title" style="display:;">算法与设计</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/70741550255/" class="nav-link">
  LeetCode
</a></li><li class="dropdown-item"><!----> <a href="/pages/17845450445/" class="nav-link">
  算法
</a></li><li class="dropdown-item"><!----> <a href="/pages/90132170217/" class="nav-link">
  数据结构
</a></li><li class="dropdown-item"><!----> <a href="/pages/50546120212/" class="nav-link">
  设计模式
</a></li><li class="dropdown-item"><!----> <a href="/pages/02344550255/" class="nav-link">
  Other
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="技能" class="dropdown-title"><!----> <span class="title" style="display:;">技能</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/82158160216/" class="nav-link">
  PMP
</a></li><li class="dropdown-item"><!----> <a href="/pages/41858590259/" class="nav-link">
  Office
</a></li><li class="dropdown-item"><!----> <a href="/pages/02359360236/" class="nav-link">
  面试
</a></li><li class="dropdown-item"><!----> <a href="/pages/73600130213/" class="nav-link">
  Bash
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="历程" class="dropdown-title"><!----> <span class="title" style="display:;">历程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/83857320232/" class="nav-link">
  流年往事
</a></li><li class="dropdown-item"><!----> <a href="/pages/93419130213/" class="nav-link">
  经验片段
</a></li><li class="dropdown-item"><!----> <a href="/pages/99744220322/" class="nav-link">
  读书杂感
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="首页" class="dropdown-title"><!----> <span class="title" style="display:;">首页</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">
  归档
</a></li><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">
  分类
</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">
  标签
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="其它" class="dropdown-title"><!----> <span class="title" style="display:;">其它</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/pages/02657130213/" class="nav-link">
  简介
</a></li><li class="dropdown-item"><!----> <a href="/pages/5390102042/" class="nav-link">
  收藏
</a></li><li class="dropdown-item"><!----> <a href="/pages/32309510451/" class="nav-link">
  有趣
</a></li><li class="dropdown-item"><!----> <a href="/pages/23313210521/" class="nav-link">
  文档
</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>JavaScript</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>vue</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>react</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><section class="sidebar-group collapsable is-sub-group depth-1"><p class="sidebar-heading open"><span>16_4</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/pages/18114480448/" class="sidebar-link">React16_4整理-开篇</a></li><li><a href="/pages/78144320432/" class="sidebar-link">React16_4整理-TodoList</a></li><li><a href="/pages/7981309049/" aria-current="page" class="active sidebar-link">React16_4整理-上阶</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/pages/7981309049/#前言" class="sidebar-link">前言</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#安装-react-开发调试工具" class="sidebar-link">安装 React 开发调试工具</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/pages/7981309049/#使用-react-开发调试工具" class="sidebar-link">使用 React 开发调试工具</a></li></ul></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#proptypes-与-defaultprops" class="sidebar-link">PropTypes 与 DefaultProps</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#props-state-与-render-函数" class="sidebar-link">Props,State 与 render 函数</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#什么是虚拟-dom" class="sidebar-link">什么是虚拟 DOM</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#深入了解虚拟-dom" class="sidebar-link">深入了解虚拟 DOM</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#虚拟-dom-中的-diff-算法" class="sidebar-link">虚拟 DOM 中的 Diff 算法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/pages/7981309049/#key-属性" class="sidebar-link">key 属性</a></li></ul></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#react-中-ref-的使用" class="sidebar-link">React 中 ref 的使用</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#react-中的生命周期函数" class="sidebar-link">React 中的生命周期函数</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/pages/7981309049/#initialization-初始化" class="sidebar-link">Initialization 初始化</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#mounting-挂载" class="sidebar-link">Mounting 挂载</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#updation-更新" class="sidebar-link">Updation 更新</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#unmounting" class="sidebar-link">Unmounting</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#整个生命周期-每一个组件都可以有生命周期" class="sidebar-link">整个生命周期，每一个组件都可以有生命周期</a></li></ul></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#生命周期函数的使用场景" class="sidebar-link">生命周期函数的使用场景</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#使用-charles-进行接口数据模拟" class="sidebar-link">使用 Charles 进行接口数据模拟</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#react-的-css-过渡动画" class="sidebar-link">React 的 CSS 过渡动画</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#使用-react-transition-group-实现单个元素的动画" class="sidebar-link">使用 react-transition-group 实现单个元素的动画</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/pages/7981309049/#使用-react-transition-group-中的-csstransition-有许多特性" class="sidebar-link">使用 react-transition-group 中的 CSSTransition 有许多特性</a></li></ul></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#使用-react-transition-group-实现多个元素间的动画" class="sidebar-link">使用 react-transition-group 实现多个元素间的动画</a></li><li class="sidebar-sub-header"><a href="/pages/7981309049/#总结" class="sidebar-link">总结</a></li></ul></li><li><a href="/pages/4241004044/" class="sidebar-link">React16_4整理-Redux开篇</a></li><li><a href="/pages/2765901041/" class="sidebar-link">React16_4整理-Redux上阶</a></li><li><a href="/pages/53933290429/" class="sidebar-link">React16_4整理-实战</a></li></ul></section></li><li><a href="/pages/2541802042/" class="sidebar-link">react心得</a></li><li><a href="/pages/56216400440/" class="sidebar-link">react设计的哲学</a></li><li><a href="/pages/64353330433/" class="sidebar-link">react上手知识点(上篇)</a></li><li><a href="/pages/67517390439/" class="sidebar-link">react上手知识点(下篇)</a></li><li><a href="/pages/21029430543/" class="sidebar-link">antd</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>低代码</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>读书会</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>线性代数</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>docker</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>auto</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>杂记</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"> <div class="theme-vdoing-wrapper bg-style-1"><div class="articleInfo-wrap" data-v-18fb2c02><div class="articleInfo" data-v-18fb2c02><ul class="breadcrumbs" data-v-18fb2c02><li data-v-18fb2c02><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-18fb2c02></a></li> <li data-v-18fb2c02><a href="/categories/?category=%E7%AC%94%E8%AE%B0" title="分类" data-v-18fb2c02>
          笔记
        </a></li> <li data-v-18fb2c02><a href="/categories/?category=react" title="分类" data-v-18fb2c02>
          react
        </a></li> <li data-v-18fb2c02><a href="/categories/?category=16_4" title="分类" data-v-18fb2c02>16_4</a></li></ul> <div class="info" data-v-18fb2c02><div title="作者" class="author iconfont icon-touxiang" data-v-18fb2c02><a href="javascript:;" data-v-18fb2c02>aiyoudiao</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-18fb2c02><a href="javascript:;" data-v-18fb2c02>2022-04-12</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-content"></div></div></div> <h1><!----> <span>
            React16_4整理-上阶
          </span></h1> <div class="theme-vdoing-content content__default"><h2 id="前言"><a href="#前言" class="header-anchor">#</a> 前言</h2> <p>围绕 React 衍生出的思考有：声明式与命令式开发、与其它框架并存、组件式的开发（组件化）、单向数据流、视图层的框架、函数式编程。
还有副作用、纯函数、Thunk函数、promise、genarator、iterator 等等。</p> <p>上篇文章中整了一个todolist应用练练手，后面也对他进行了优化。接下来说点深入一点的东西，比如怎么调试，类型校验，虚拟dom和diff，生命周期，以及使用工具来进行接口mock，css过渡动画，单、多元素过渡动画等等。</p> <h2 id="安装-react-开发调试工具"><a href="#安装-react-开发调试工具" class="header-anchor">#</a> 安装 React 开发调试工具</h2> <p>下载 <code>React Developer Tools</code> 插件 然后放到 Chrome 浏览器中去，在开发环境下使用这个插件，这个插件的图标会显示<code>红色</code>。如果你的页面不是 React 开发的，那么图标会显示<code>灰色</code>如果是线上的环境，那么图标会显示为<code>黑色</code>。</p> <h3 id="使用-react-开发调试工具"><a href="#使用-react-开发调试工具" class="header-anchor">#</a> 使用 React 开发调试工具</h3> <p>打开开发人员工具，选择 React 选项卡，这时候就可以看到页面标签以 React 组件的方式显示。<br>
使用这个组件来调试组件间传值的时候，就不需要使用 console.log()来打印了。只需要点击这个组件，然后在右侧实时的监控整个组件的状态即可。</p> <h2 id="proptypes-与-defaultprops"><a href="#proptypes-与-defaultprops" class="header-anchor">#</a> PropTypes 与 DefaultProps</h2> <p>对传递过来的属性的类型做校验，如果不符合要求，就会自动警告，用来限制传值时的数据类型，对开发是比较友好的。</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code><span class="token comment">// 你要下载这个模块儿，然后才能引入，脚手架工具中自带了</span>
<span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">'prop-types'</span><span class="token punctuation">;</span>

<span class="token comment">// ...</span>

<span class="token comment">// 对当前组件.props属性 使用 组件.propTypes 的数据类型进行校验</span>
TodoItem<span class="token punctuation">.</span>propTypes <span class="token operator">=</span> <span class="token punctuation">{</span>

    <span class="token punctuation">{</span><span class="token comment">/*表示传递过来的content属性一定要是string类型*/</span><span class="token punctuation">}</span>
    content<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token builtin">string</span><span class="token punctuation">,</span>

    <span class="token punctuation">{</span><span class="token comment">/* 一定要是一个函数 */</span><span class="token punctuation">}</span>
    deleteItem<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">,</span>

    <span class="token punctuation">{</span><span class="token comment">/* 一定要是一个数字*/</span><span class="token punctuation">}</span>
    index<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token builtin">number</span><span class="token punctuation">,</span>

    <span class="token punctuation">{</span><span class="token comment">/* 表示传递过来的test属性一定要是string类型的，并且这个test参数必须传递过来了，否则就警告*/</span><span class="token punctuation">}</span>
    test<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token builtin">string</span><span class="token punctuation">.</span>isReuqired<span class="token punctuation">,</span>

    <span class="token punctuation">{</span><span class="token comment">/*表示test2 必须是一个数组，数组的组成内容可以一个string类型或者number类型*/</span><span class="token punctuation">}</span>
    test2<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token function">arrayOf</span><span class="token punctuation">(</span>PropTypes<span class="token punctuation">.</span><span class="token builtin">string</span><span class="token punctuation">,</span> PropTypes<span class="token punctuation">.</span><span class="token builtin">number</span><span class="token punctuation">)</span><span class="token punctuation">,</span>

    <span class="token punctuation">{</span><span class="token comment">/*表示test3 必须是一个string类型或者number类型*/</span><span class="token punctuation">}</span>
    test3<span class="token operator">:</span> PropTypes<span class="token punctuation">.</span><span class="token function">oneOfType</span><span class="token punctuation">(</span><span class="token punctuation">[</span>PropTypes<span class="token punctuation">.</span><span class="token builtin">string</span><span class="token punctuation">,</span> PropTypes<span class="token punctuation">.</span><span class="token builtin">number</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 给当前组件.props中的成员设置默认值</span>
TodoItem<span class="token punctuation">.</span>defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span>
    test<span class="token operator">:</span> <span class="token string">'hello world'</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="props-state-与-render-函数"><a href="#props-state-与-render-函数" class="header-anchor">#</a> Props,State 与 render 函数</h2> <p>当组件的 state 或者 props 发生改变的时候，组件的 render 函数就会重新执行。<br>
实际<code>原理</code>还是 <code>setState</code>方法<code>被调用</code>了，然后执行了<code>re-render</code>(patch)的方法，重新渲染页面的组件。</p> <h2 id="什么是虚拟-dom"><a href="#什么是虚拟-dom" class="header-anchor">#</a> 什么是虚拟 DOM</h2> <p>state 数据，JSX 模板。数据+模板 结合，生成虚拟 DOM ，由虚拟 DOM 生成真实 DOM 来显示。<br>
state 发生改变，数据+模板 结合，生成新虚拟 DOM ，对比之前的旧的虚拟 DOM，找出差异点，不是整版替换，而是经过新旧虚拟 DOM 节点对比。<br>
由框架直接操作 DOM，将变化的旧节点的 DOM 替换成新的节点的 DOM。<br>
虚拟 DOM 就是使用 JS 模拟 DOM，目的是为了提升性能，因为直接操作太消耗性能，一个 DOM 对象有几百个成员，这样会造成进行节点对比的时候极大的损耗性能。</p> <h2 id="深入了解虚拟-dom"><a href="#深入了解虚拟-dom" class="header-anchor">#</a> 深入了解虚拟 DOM</h2> <p>JSX 语法其实是虚拟 dom 创建的语法糖，最后会被统一的转换为<code>React.createElement()</code>方法，这个方法创建虚拟 dom。<br>
因为虚拟 DOM 所以性能提升了，它使得跨端应用得以实现，如 React Native。<br>
在 React Native 中让虚拟 DOM 不去生成真实的 DOM 而是生成一些原生的组件，那么就能实现很好的重用了，这样就能够让 React 即能生成网页应用，也能够生成原生应用。</p> <h2 id="虚拟-dom-中的-diff-算法"><a href="#虚拟-dom-中的-diff-算法" class="header-anchor">#</a> 虚拟 DOM 中的 Diff 算法</h2> <p>调用 setState 才会让数据发生变化，setState 是异步，这么做是为了提升性能。<br>
如果你连续调用三次 setState，那么 React 会将三次操作合并成一次，然后再去调用 re-render 的方法渲染页面，这也是为什么 setState 是异步的原因。<br>
同层虚拟 DOM 比较，从上往下进行比较，找到差异之后去更新真实的 DOM，如果有一层有差异就不会往下比较了，这样比对的速度非常快。</p> <h3 id="key-属性"><a href="#key-属性" class="header-anchor">#</a> key 属性</h3> <p>key 属性的设置，就是给虚拟 dom 的节点设置名字。</p> <p>假如有一个数组，原来里面有五个数据，如果你又增加了一个数据，这时候你如果要新旧虚拟 dom 节点进行对比，就会出现双层 for 循环的对比方式了。<br>
这样很麻烦，如果你设置了 key 属性，那么就直接遍历 key 值相同的进行对比，这样就只是单重 for 循环的对比了。<br>
这样就只用把新增加的数据添加到 ul 的 dom 中就可以了。所以不要把 key 属性的值设置为 index，那样没法保证原始的虚拟 dom 节点的 key 值与新的虚拟 dom 节点的 key 值一致了。<br>
因为可能会发生数组元素的位置变化，那时候新的虚拟 dom 节点的 key 值是整版替换的，相当于没有设置。<br>
例如 你删除了一个数组元素，然后 key 值等于 index，这时候 key 值相当于整版替换了，因为 index 值是数组元素的全新的下标。<br>
key 值很不稳定，key 值需要很稳定，例如你将 key 值设置为 item，这样就确定了唯一性。<br>
能不用 index 作为 key 值的时候就不用 index 作为 key 值，key 值的设置是为了提高虚拟 dom 比对的性能。</p> <h2 id="react-中-ref-的使用"><a href="#react-中-ref-的使用" class="header-anchor">#</a> React 中 ref 的使用</h2> <p>之前需要通过<code>e.target</code>来获取事件源</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token function">handleInput</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 通过事件源的方式获取页面标签了</span>
        <span class="token keyword">const</span> input <span class="token operator">=</span> e<span class="token punctuation">.</span>target<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><p>现在可以通过 ref 来获取页面中的 dom</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token punctuation">{</span><span class="token comment">/*在页面标签中添加ref*/</span><span class="token punctuation">}</span>
    <span class="token operator">&lt;</span>input ref <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>input <span class="token operator">=</span> input<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>

    <span class="token function">handleInput</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 这样就能够获取 页面中的指定input了</span>
        <span class="token keyword">const</span> input <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>input<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><p>但是不推荐使用 ref，React 中推荐使用以数据驱动的方式编写代码，不要直接去操作 DOM。<br>
setState 操作是异步的，如果你在 setState 中清空了输入框的内容，然后再 setState 的下面通过 dom 获取了输入框的内容，这时候就会发现值还没有清空。<br>
因为同步代码会被先执行，异步代码是等同步代码执行完毕后才会执行的。
虽然你可以通过 setState 的回调函数来使用 dom 实时的获取输入框中的内容，当 setState 异步操作结束后才会去执行回调函数，那时候就能够实时的获取 dom 中的内容了。<br>
但是如果你设置 dom 的内容，会导致对比时出现错误。如果在做一些极其复杂的业务时可以考虑使用，如操作动画时。</p> <h2 id="react-中的生命周期函数"><a href="#react-中的生命周期函数" class="header-anchor">#</a> React 中的生命周期函数</h2> <p>生命周期函数是指在某一个时刻组件会自动调用执行的函数</p> <h3 id="initialization-初始化"><a href="#initialization-初始化" class="header-anchor">#</a> Initialization 初始化</h3> <p><code>Initialization</code>：在组件初始化的时刻自动执行，相当于<code>constructor</code>构造函数里面做一些<code>props</code>和<code>state</code>的设置。</p> <h3 id="mounting-挂载"><a href="#mounting-挂载" class="header-anchor">#</a> Mounting 挂载</h3> <p><code>componentWillMount</code>：在组件即将被挂载到页面的时刻自动执行<br> <code>render</code>：在组件挂载到页面的时刻自动执行<br> <code>componentDidMount</code>：在组件挂载到页面之后的时刻自动执行</p> <h3 id="updation-更新"><a href="#updation-更新" class="header-anchor">#</a> Updation 更新</h3> <h4 id="props-发生变化"><a href="#props-发生变化" class="header-anchor">#</a> props 发生变化</h4> <p><code>componentWillReceiveProps</code>：当前子组件第二次及第二次之后接收了父组件传递属性的时刻都会被执行，也就是父组件执行 render 更新操作时，再次给子组件传递属性时会执行这个生命周期函数。<br> <code>shouldComponentUpdate</code>：在组件确定需要更新之前自动执行，需要返回一个 bool 值，这个 bool 值用来确定是否需要更新当前组件，如果返回 false 就不会执行后面的更新操作了，也就是下面的函数都不会再执行了。<br> <code>componentWillUpdate</code>：在组件确定需要更新之后，在组件真正更新之前会自动执行。<br> <code>render</code>：组件真正更新的时刻自动执行，也就是重新渲染 DOM。<br> <code>componentDidUpdate</code>：组件真正更新完成之后会自动执行。</p> <h4 id="states-发生变化"><a href="#states-发生变化" class="header-anchor">#</a> states 发生变化</h4> <p><code>shouldComponentUpdate</code>：在组件确定需要更新之前自动执行，需要返回一个 bool 值，这个 bool 值用来确定是否需要更新当前组件，如果返回 false 就不会执行后面的更新操作了，也就是下面的函数都不会再执行了。<br> <code>componentWillUpdate</code>：在组件确定需要更新之后，在组件真正更新之前会自动执行。<br> <code>render</code>：组件真正更新的时刻自动执行，也就是重新渲染 DOM。<br> <code>componentDidUpdate</code>：组件真正更新完成之后会自动执行。</p> <h3 id="unmounting"><a href="#unmounting" class="header-anchor">#</a> Unmounting</h3> <p><code>componentWillUnmount</code>：在组件在页面上即将被去除的时刻会被执行，比如子组件是一个列表项，你删除这个列表项时就会自动执行这个函数了。</p> <h3 id="整个生命周期-每一个组件都可以有生命周期"><a href="#整个生命周期-每一个组件都可以有生命周期" class="header-anchor">#</a> 整个生命周期，每一个组件都可以有生命周期</h3> <p>初始化 <code>constructor</code><br>
首次挂载组件到页面之前 <code>componentWillMount</code><br>
首次挂载组件到页面时 <code>render</code><br>
首次挂载组件到页面之后 <code>componentDidMount</code><br>
第二次及第二次之后从父组件那里获取 props 时 <code>componentWillReceiveProps</code><br>
确定是否需要更新组件 <code>shouldComponentUpdate</code><br>
真正更新组件之前 <code>componentWillUpdate</code><br>
真正更新组件时 <code>render</code><br>
真正更新组件之后 <code>componentDidUpdate</code><br>
组件在页面中被卸载时 <code>componentWillUnmount</code></p> <h2 id="生命周期函数的使用场景"><a href="#生命周期函数的使用场景" class="header-anchor">#</a> 生命周期函数的使用场景</h2> <p>组件继承的<code>Component</code>中默认<code>预置</code>了<code>所有</code>的<code>生命周期函数</code>，<code>唯独没有预置render函数</code>。<br> <code>render</code>函数必须有，因为它用来生成虚拟 DOM 的，没有虚拟 DOM 那就完蛋了。</p> <p><code>shouldComponentUpdate</code> 可以用来父组件<code>render</code>时<code>自动</code>调用<code>子</code>组件的<code>render前</code>的拒绝操作，也就是父组件更新时不更新子组件，子组件只会进行首次渲染。<br>
主要是减少子组件 render 函数的不必要执行，虽然虚拟 dom 的对比比真实 dom 的对比要性能更优，但是减少虚拟 dom 的生成与对比就能够让性能更优。<br>
在拒绝更新操作之前要进行判断，如判断传递过来的 props 是否与当前的 props 不同</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token function">shouldComponentUpdate</span> <span class="token punctuation">(</span>nextProps<span class="token punctuation">,</span> nextState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 如果传递过来的props与当前的props不一样，说明子组件需要更新了</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>nextProps<span class="token punctuation">.</span>content <span class="token operator">!==</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>content<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        <span class="token comment">// 说明子组件没有重新被渲染的必要</span>
            <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
</code></pre></div><p><code>constructor</code> 可以用来绑定当前方法的作用域，只需要绑定一次即可，<code>减少</code>了<code>多次绑定</code>方法的<code>作用域</code>，这样就可以在事件绑定时不需要每次都<code>.bind(this)</code>。</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token function">constructor</span> <span class="token punctuation">(</span>props<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>handleClick <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">handleClick</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre></div><p><code>componentDidMount</code> 可以用来存放 ajax 请求，它永远都不会有问题，因为它只会执行一次。其实你也可以放到 constructor 中，因为它也是只执行一次的，但是它里面已经放了很多初始化 props 和 state 的操作。操作 ajax 可以使用 axios</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token keyword">import</span> Axios <span class="token keyword">from</span> <span class="token string">'axios'</span><span class="token punctuation">;</span>

    <span class="token function">componentDidMount</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Axios<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/todolist'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'success'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'bad'</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
</code></pre></div><h2 id="使用-charles-进行接口数据模拟"><a href="#使用-charles-进行接口数据模拟" class="header-anchor">#</a> 使用 Charles 进行接口数据模拟</h2> <p><strong>使用教程：</strong></p> <p>下载 Charles<br>
打开 Charles 后选择选项卡 Tools<br>
选择 Map Local 选项<br>
点击 Add 按钮 设置代理协议、主机、端口、路径<br>
然后选择被代理的文件(json 文件) 点击 ok<br>
之后选中 Enable Map Local 点击 OK 按钮<br>
本次设置完成</p> <p>它的作用是抓取请求，并且对请求做出处理。它相当于一个中间的代理服务器。<br>
在前端开发的时候，没有这个接口的数据，你可以使用 json 自己模拟这个接口的数据。使用 Charles 来进行模拟。<br>
josn 文件中的对象或者数组，键值对必须使用双引号，单引号会被认为整个对象或者数组是一个字符串。</p> <h2 id="react-的-css-过渡动画"><a href="#react-的-css-过渡动画" class="header-anchor">#</a> React 的 CSS 过渡动画</h2> <p><strong>过渡</strong></p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token comment">/*需要过渡的属性 持续时间 过渡效果类型 延迟时间*/</span>
<span class="token property">transition</span><span class="token punctuation">:</span> all 1s ease-in 0s<span class="token punctuation">;</span>
</code></pre></div><p><strong>动画</strong></p> <div class="language-css extra-class"><pre class="language-css"><code><span class="token comment">/*先定义动画*/</span>
<span class="token atrule"><span class="token rule">@keyframes</span> dong</span> <span class="token punctuation">{</span>
    <span class="token selector">from</span> <span class="token punctuation">{</span>
        <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token selector">to</span> <span class="token punctuation">{</span>
        <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token atrule"><span class="token rule">@keyframes</span> dong2</span> <span class="token punctuation">{</span>
    <span class="token selector">0%</span> <span class="token punctuation">{</span>
        <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token selector">100%</span> <span class="token punctuation">{</span>
        <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">/*使用动画: 动画名(必写) 持续时间(必写) 执行次数 动画方向 延迟时间 动画类型 结束时的状态*/</span>
<span class="token property">animation</span><span class="token punctuation">:</span> dong 2s 1 normal 0s ease-in forwards<span class="token punctuation">;</span>
</code></pre></div><h2 id="使用-react-transition-group-实现单个元素的动画"><a href="#使用-react-transition-group-实现单个元素的动画" class="header-anchor">#</a> 使用 react-transition-group 实现单个元素的动画</h2> <p>先打开<code>github</code> 搜索这个开源项目<br>
查看 里面对应的文档<br>
使用命令安装：<code>yarn add react-transition-group</code>或者<code>npm install react-transition-group --save</code><br>
使用 <code>react-transition-group</code>中的<code>CSSTransition</code></p> <div class="language-tsx extra-class"><pre class="language-tsx"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>CSSTransition<span class="token punctuation">}</span>  <span class="token keyword">from</span> <span class="token string">'react-transition-group'</span><span class="token punctuation">;</span>

<span class="token operator">&lt;</span>CSSTransition
    <span class="token punctuation">{</span><span class="token comment">/*  出入场动画设置，通过in的属性值来进行切换 true为入场 false 为出场*/</span><span class="token punctuation">}</span>
    <span class="token keyword">in</span><span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>show<span class="token punctuation">}</span>
    <span class="token punctuation">{</span><span class="token comment">/* 动画持续时间 */</span><span class="token punctuation">}</span>
    timeout<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">1000</span><span class="token punctuation">}</span>
    <span class="token punctuation">{</span><span class="token comment">/* 切换的css类名前缀 css文件中会有对应的类 如.fade-enter */</span><span class="token punctuation">}</span>
    classNames<span class="token operator">=</span><span class="token string">'fade'</span>
    <span class="token punctuation">{</span><span class="token comment">/* 出场动画执行完毕之后 组件就会从页面上被卸载 */</span><span class="token punctuation">}</span>
    unmountOnExit
    onExited<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
            <span class="token comment">//直接进行DOM操作</span>
            <span class="token comment">//el.style.color=&quot;#f00&quot;;</span>
            <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token operator">&gt;</span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span><span class="token plain-text">只是一个div</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">CSSTransition</span></span><span class="token punctuation">&gt;</span></span>
</code></pre></div><div class="language-css extra-class"><pre class="language-css"><code><span class="token comment">/* 第一次入场 */</span>
<span class="token selector">.fade-appear</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* 第一次入场中 */</span>
<span class="token selector">.fade-appear-active</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
    <span class="token property">transition</span><span class="token punctuation">:</span> opacity 1s ease-in<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/*-----------------------------------*/</span>

<span class="token comment">/* 入场动画执行前的时候  第一个时刻 */</span>
<span class="token selector">.fade-enter</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* 入场动画在执行的时候 第二个时刻 */</span>
<span class="token selector">.fade-enter-active</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
    <span class="token property">transition</span><span class="token punctuation">:</span> opacity 1s ease-in<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* 入场动画完全执行完毕后 第三个时刻*/</span>
<span class="token selector">.fade-enter-done</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/*---------------------------*/</span>

<span class="token comment">/* 出场动画执行前的时候  第四个时刻 */</span>
<span class="token selector">.fade-exit</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* 出场动画在执行的时候 第五个时刻*/</span>
<span class="token selector">.fade-exit-active</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token property">transition</span><span class="token punctuation">:</span> opacity 1s ease-in<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">/* 出场动画完全执行完毕的时候 第六个时刻 */</span>
<span class="token selector">.fade-exit-done</span> <span class="token punctuation">{</span>
    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="使用-react-transition-group-中的-csstransition-有许多特性"><a href="#使用-react-transition-group-中的-csstransition-有许多特性" class="header-anchor">#</a> 使用 react-transition-group 中的 CSSTransition 有许多特性</h3> <p>可以切换 css 中定义的类，<code>前缀可以改</code>，<code>后缀是固定</code>的。<br> <code>前缀改了</code>之后，<code>CSSTransition</code>中的<code>classNames</code>也要<code>改为新</code>的<code>前缀</code>名。<br> <code>.fade-appear</code> 只在第一次入场时自动切换<br> <code>.fade-appear-active</code> 只在第一次入场中自动切换<br> <code>.fade-enter</code> 入场前<br> <code>.fade-enter-active</code> 入场中<br> <code>.fade-enter-done</code> 入场后<br> <code>.fade-exit</code> 出场前<br> <code>.fade-exit-active</code> 出场中<br> <code>.fade-exit-done</code> 出场后</p> <p>还可以操作<code>JS DOM</code> 因为<code>CSSTransition</code>里面<code>内置</code>了许多的<code>生命周期钩子</code>函数，css<code>状态类</code>与下面的<code>生命周期钩子函数对应</code><br> <code>onEnter</code> 入场前<br> <code>onEntering</code> 入场中<br> <code>onEntered</code> 入场后<br> <code>onExit</code> 出场前<br> <code>onExiting</code> 场中<br> <code>onExited</code> 出场后</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code>    <span class="token comment">/* 传进去的参数是 CSSTransition中最外层的DOM */</span>
    onExited <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token comment">//直接进行DOM操作</span>
        <span class="token comment">//el.style.color = &quot;#f00&quot;;</span>
        <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">}</span>
</code></pre></div><p><code>unmountOnExit</code>：表示在<code>CSSTransition</code>中的<code>出场动画执行完毕后</code>就<code>会从页面中被移除</code>掉。</p> <h2 id="使用-react-transition-group-实现多个元素间的动画"><a href="#使用-react-transition-group-实现多个元素间的动画" class="header-anchor">#</a> 使用 react-transition-group 实现多个元素间的动画</h2> <p>使用 <code>react-transition-group</code>的<code>TransitionGroup</code>配合<code>CSSTransition</code>来<code>实现多</code>个组件的<code>动画</code>效果</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>CSSTransition<span class="token punctuation">,</span>TransitionGroup<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-transition-group'</span>

<span class="token punctuation">{</span><span class="token comment">/* 在外面嵌套一层 TransitionGroup 标签*/</span><span class="token punctuation">}</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">TransitionGroup</span></span><span class="token punctuation">&gt;</span></span><span class="token plain-text">
    </span><span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span>item<span class="token punctuation">,</span>index<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token punctuation">(</span>
                <span class="token punctuation">{</span><span class="token comment">/* 每个元素都设置一下 动画，只不过in属性不要了，因为自动为true了*/</span><span class="token punctuation">}</span>
                <span class="token operator">&lt;</span>CSSTransition
                    timeout <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">1000</span><span class="token punctuation">}</span>  <span class="token comment">// 持续时间</span>
                    classNames <span class="token operator">=</span> <span class="token string">&quot;fade&quot;</span> <span class="token comment">// 切换的类前缀</span>
                    unmountOnExit <span class="token comment">// 出场时移除这个组件</span>
                    appear <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token boolean">true</span><span class="token punctuation">}</span> <span class="token comment">// 首次入场 是否自动切换 入场动画</span>
                    onEntered <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token comment">// 出场后的钩子函数</span>
                        <span class="token comment">//直接进行DOM操作</span>
                        el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>color <span class="token operator">=</span> <span class="token string">&quot;red&quot;</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span><span class="token punctuation">}</span>
                    key <span class="token operator">=</span> <span class="token punctuation">{</span>index<span class="token punctuation">}</span>
                <span class="token operator">&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">{</span>item<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">CSSTransition</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token punctuation">)</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token plain-text">
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">TransitionGroup</span></span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h2> <p>react调试有专门的浏览器插件。react的props类型校验用的是prop-types。</p> <p>虚拟dom和diff，这两个也是笔记常见的，我写过一篇实现vdom和diff的文章 <a href="https://juejin.cn/post/7084503737213354014" target="_blank" rel="noopener noreferrer">https://juejin.cn/post/7084503737213354014<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。</p> <p>生命周期只是16.4的时候，现在的话，很多生命周期都变了，主要的componentDidMount、shouldComponentUpdate、componentDidUpdate、componentWillUnmount都没变化。react的vdom之前是树，循环加递归的去判断它是否发生变化。现在是fiber链表，循环加打打标记的来判断它是否发生变化。<br>
fiber的diff算法是在render中执行的，为了保证应对fiber的链式渲染，所以render之前的那些方法 比如 componentWillMount、componentWillReceiveProps、componentWillUpdate，它们就不需要了。<br>
因为它可能会在render之前改变state属性，会造成优先级不正确的问题，于是react觉得这些方法会存在风险，所以把它们直接干掉了。不过shouldComponentUpdate保留下来了，它不会改变state。</p> <p>使用工具来进行接口mock，这个现在有插件可以直接实现，几乎是基于mockjs、webpack-dev-server、express，或者其它更好的工具，但原理大都一样，都是做个中间层代理。<br>
css过渡 transition、动画 animation，单CSSTransition、多TransitionGroup元素过渡动画等等，都是基于CSS3做的封装，其实也并不难，当然深入会有难度，但是深入得靠自己实践研究了。之后有空的话，我把CSS3的笔记和案例也进行整理做下输出。</p></div></div> <div class="page-edit"><!----> <div class="tags"><a href="/tags/?tag=react" title="标签">#react</a></div> <div class="last-updated"><span class="prefix">上次更新时间:</span> <span class="time">10年18月2023日 01时57分53秒</span></div></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/78144320432/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">React16_4整理-TodoList</div></a> <a href="/pages/4241004044/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">React16_4整理-Redux开篇</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/78144320432/" class="prev">React16_4整理-TodoList</a></span> <span class="next"><a href="/pages/4241004044/"> React16_4整理-Redux开篇 </a>
        →
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/pages/45343271027/"><div>01.数据结构导论一览.md</div></a> <span>10-16</span></dt></dl><dl><dd>02</dd> <dt><a href="/pages/38850370637/"><div>30.2023年06月04日.md</div></a> <span>06-04</span></dt></dl><dl><dd>03</dd> <dt><a href="/pages/74707370537/"><div>08.与测量相关.md</div></a> <span>05-06</span></dt></dl> <dl><dd></dd> <dt><a href="/archives/" class="more">更多文章&gt;</a></dt></dl></div></div> </main></div> <div class="footer"><!----> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2017-2023
    <span class="link">aiyoudiao 码二</span> <span>备案号：</span> <a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank" title="备案号">鄂ICP备2022002654号-1</a></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div></div> <!----> <!----> <!----></div><div class="global-ui"><div></div><APlayer audio="" fixed="true" theme="#b7daff" loop="loop" order="list" preload="auto" volume="0.7" mutex="true" lrc-type="3" list-max-height="250" storage-name="vuepress-plugin-meting" id="aplayer-fixed"></APlayer><div id="VuepressPluginLive2d"></div></div></div>
    <script src="/assets/js/app.bd2fbc77.js" defer></script><script src="/assets/js/3.72c9c947.js" defer></script><script src="/assets/js/112.352fa217.js" defer></script><script src="/assets/js/42.4251ca36.js" defer></script>
  </body>
</html>
